package com.ruoyi.core.job;

import com.alibaba.fastjson.JSON;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.AppType;
import com.ruoyi.common.enums.ProductType;
import com.ruoyi.common.httpSdk.AbstractRequest;
import com.ruoyi.common.httpSdk.AbstractResponse;
import com.ruoyi.common.httpSdk.client.CommonClient;
import com.ruoyi.common.httpSdk.request.*;
import com.ruoyi.common.utils.RedisCacheKeyHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.email.EmailUtils;
import com.ruoyi.core.domain.ClientProductUser;
import com.ruoyi.core.domain.ServerConfig;
import com.ruoyi.core.domain.custombean.ClientProductCookieQueryResult;
import com.ruoyi.core.lock.ULock;
import com.ruoyi.core.mapper.ClientProductUserMapper;
import com.ruoyi.core.mapper.ServerConfigMapper;
import com.ruoyi.core.service.ClientOperationService;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

/**
 * @Author xiaom
 * @Date 2021/2/25 11:37
 * @Version 1.0.0
 * @Description <>
 **/
@Component
@Slf4j
public class ConfigJob {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private SysConfigMapper sysConfigMapper;

    @Autowired
    private ClientProductUserMapper clientProductUserMapper;

    @Autowired
    private EmailUtils emailUtils;

    @Autowired
    private ClientOperationService clientOperationService;

    @Autowired
    private ServerConfigMapper serverConfigMapper;

    @PostConstruct
    public void initData() {
        ServerConfig serverConfig = serverConfigMapper.selectAvailableNode();
        if (serverConfig == null) {
            log.error("初始化服务器节点配置失败,不存在可用节点");
        } else {
            AbstractRequest.baseUrl = serverConfig.getIp();
            log.info("服务器当前选择节点:{}  地址:{}", serverConfig.getServerName(), serverConfig.getIp());
        }
    }

    @Scheduled(fixedDelay = 1000 * 5)
    public void refreshServerNode() {
        this.initData();
    }


    @Scheduled(fixedDelay = 1000 * 60)
    public void refreshSysConfig() {
        List<SysConfig> list = sysConfigMapper.selectAll();
        if (list == null || list.isEmpty()) {
            log.error("无系统配置项....");
            return;
        }
        list.forEach(config -> {
            redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
        });
        log.info("SysConfig Refresh Success...");
    }

    @Scheduled(fixedDelay = 1000 * 3)
    public void refreshProductCookies() {
        //获取所有cookie
        List<ClientProductCookieQueryResult> results = clientProductUserMapper.findAllProductCookies(null);
        if (results == null || results.isEmpty()) {
            log.error("无可用cookie，请检查");
            return;
        }
        HashMap<String, List<String>> cookiesMap = new HashMap<>();
        results.forEach(item -> {
            if (item.getAvailable() == 0) {
                return;
            }
            List<String> cookies = cookiesMap.get(item.getProductName());
            if (cookies == null) {
                cookies = new ArrayList<>();
            }
            cookies.add(item.getCookie());
            cookiesMap.put(item.getProductName(), cookies);
        });

        //缓存至redis
        cookiesMap.keySet().forEach(key -> {
            List<String> cks = cookiesMap.get(key);
            String cckey = RedisCacheKeyHelper.getProxyCookiesKey(key);
            redisCache.deleteObject(cckey);
            redisCache.setCacheSet(cckey, new HashSet<>(cks));
        });

    }

    /**
     * 检查cookie是否有效
     */
    @Scheduled(fixedDelay = 1000 * 10)
    public void checkCookieAvailable() {
        //获取所有cookie
        List<ClientProductCookieQueryResult> results = clientProductUserMapper.findAllProductCookies(null);
        //调用接口,看是否成功返回
        if (results == null || results.isEmpty()) {
            log.info("数据库未设置任何cookie");
            return;
        }
        results.forEach(item -> {
            if (item.getProductName() == null || StringUtils.isEmpty(item.getCookie())) {
                return;
            }
            boolean valid;
            if (item.getProductName().equals(ProductType.junglescout.getName()) || item.getProductName().equals(ProductType.junglescoutv2.getName())) {
                valid = valid(getValidJunglescout(item.getCookie()));
                if (!valid) {
                    refreshJunglescoutCookie(item);
                }
            } else if (item.getProductName().equals(ProductType.jsPlugin.getName())) {
                valid = valid(getValidJsPluginRequest(item.getCookie()));
                if (!valid) {
                    refreshJsPluginCookie(item);
                }
            } else if (item.getProductName().equals(ProductType.elves.getName())) {
                valid = valid(getValidElvesRequest(item.getCookie()));
                if (!valid) {
                    refreshElvesCookie(item);
                }
            } else if (item.getProductName().equals(ProductType.elves_plugin.getName())) {
                valid = valid(getValidElvesPluginRequest(item.getCookie()));
                if (!valid) {
                    refreshElvesPluginCookie(item);
                }
            }

//            log.info("检查cookie. 名称:[{}] 账户:[{}] 状态:[{}]",item.getProductName(),item.getEmail(),valid);
//            invalidAfter(valid,item);
//            clientProductUserMapper.updateCookieAvailable(item.getId(),valid ? 1 : 0);
        });
    }

    /**
     * 检查merchant cookie
     */
    @Scheduled(fixedDelay = 1000 * 10)
    public void checkMerchantCookie() {
        log.info("checkMerchantCookie....");
        List<ClientProductCookieQueryResult> results = clientProductUserMapper.findAllProductCookies(null);
        results.forEach(item -> {
            if (item.getProductName() == null) {
                return;
            }
            boolean valid = true;
            if (isMerchantType(item.getProductName())) {
                log.info("检查cookie. 名称:[{}] 账户:[{}]", item.getProductName(), item.getEmail());
                valid = valid(getValidMerchantRequest(item.getCookie()));
                log.info("检查cookie. 名称:[{}] 账户:[{}] 状态:[{}]", item.getProductName(), item.getEmail(), valid);
                if (!valid) {
                    refreshMerchantCookie(item);
                }
            } else if (item.getProductName().equals(ProductType.helium10.getName())) {
                log.info("检查cookie. 名称:[{}] 账户:[{}]", item.getProductName(), item.getEmail());
                valid = valid(getValidHeliumRequest(item.getCookie()));
                log.info("检查cookie. 名称:[{}] 账户:[{}] 状态:[{}]", item.getProductName(), item.getEmail(), valid);
                if (!valid) {
                    refreshHeliumCookie(item);
                }
            }
            invalidAfter(valid, item);
            clientProductUserMapper.updateCookieAvailable(item.getId(), valid ? 1 : 0);
        });
    }

    private boolean isMerchantType(String productName) {
        return productName.equals(ProductType.merchantwords.getName()) || productName.equals(ProductType.merchantwordsWeb.getName()) || productName.equals(ProductType.merchantwordsv2.getName());
    }

    private void invalidAfter(boolean valid, ClientProductCookieQueryResult item) {
        boolean isH10 = item.getProductName().equals(ProductType.helium10.getName());
        if (!valid && isH10) {
            new Thread(() -> {
                //amzzytz@163.com
                emailUtils.sendSimpleMail("amzzytz@163.com", "cookie过期提醒", "账户:[" + item.getEmail() + "] 产品名称:[" + item.getProductName() + "]");
            }).start();
        }

        //如果是merchant失效,则启用备用cookie方案
//        if(!valid && isH10){
//            if(StringUtils.isEmpty(item.getBackUpCookie())){
//                return;
//            }
//            //更新备用cookie到主cookie中
//            ClientProductUser clientProductUser = new ClientProductUser();
//            clientProductUser.setId(item.getId());
//            clientProductUser.setCookie(item.getBackUpCookie());
//            clientProductUserMapper.update(clientProductUser);
//        }
    }

    private void refreshElvesPluginCookie(ClientProductCookieQueryResult item) {
        log.info("产品名称:[{}] 账户:[{}] 执行自动刷新操作", item.getProductName(), item.getEmail());
        clientOperationService.cookieRefresh(item.getId(), AppType.ELVES_PLUGIN);
    }

    private void refreshJsPluginCookie(ClientProductCookieQueryResult item) {
        log.info("产品名称:[{}] 账户:[{}] 执行自动刷新操作", item.getProductName(), item.getEmail());
        clientOperationService.jsPluginCookieRefresh(null, new Long[]{item.getClientProductId()});
    }

    private void refreshJunglescoutCookie(ClientProductCookieQueryResult item) {
        log.info("产品名称:[{}] 账户:[{}] 执行自动刷新操作", item.getProductName(), item.getEmail());
        clientOperationService.jungleScoutCookieRefresh(null, new Long[]{item.getClientProductId()});
    }

    private void refreshMerchantCookie(ClientProductCookieQueryResult item) {
        log.info("产品名称:[{}] 账户:[{}] 执行自动刷新操作", item.getProductName(), item.getEmail());
        clientOperationService.cookieRefresh(item.getId(), AppType.MERCHANTWORD);
    }

    private void refreshHeliumCookie(ClientProductCookieQueryResult item) {
        log.info("产品名称:[{}] 账户:[{}] 执行自动刷新操作", item.getProductName(), item.getEmail());
        clientOperationService.cookieRefresh(item.getId(), AppType.HELIUM);
    }

    private void refreshElvesCookie(ClientProductCookieQueryResult item) {
        log.info("产品名称:[{}] 账户:[{}] 执行自动刷新操作", item.getProductName(), item.getEmail());
        clientOperationService.cookieRefresh(item.getId(), AppType.ELVES);
    }

    private Request getValidJunglescout(String cookie) {
        ValidJunlescoutRequest request = new ValidJunlescoutRequest(RequestMethod.POST);
        request.setCookie(cookie);
        return request;
    }

    private Request getValidMerchantRequest(String cookie) {
        ValidMerchantRequest request = new ValidMerchantRequest(RequestMethod.POST);
        request.setCookie(cookie);
        return request;
    }

    private Request getValidHeliumRequest(String cookie) {
        ValidHeliumRequest request = new ValidHeliumRequest();
        request.setCookie(cookie);
        return request;
    }

    private Request getValidJsPluginRequest(String cookie) {
        try {
            String ck = JSON.parseObject(cookie).getString("daily_token").trim();
            ValidJsPluginRequest request = new ValidJsPluginRequest();
            request.setCookie(ck);
            return request;
        } catch (Exception e) {
            log.error("JS插件验证 cookie异常 cookie:${}", cookie);
            return null;
        }
    }

    private Request getValidElvesRequest(String cookie) {
        ValidElvesRequest request = new ValidElvesRequest(RequestMethod.POST);
        request.setCookie(cookie);
        return request;
    }

    private Request getValidElvesPluginRequest(String cookie) {
        ValidElvesPluginRequest request = new ValidElvesPluginRequest(RequestMethod.POST);
        request.setCookie(cookie);
        return request;
    }

    private Boolean valid(Request request) {
        try {
            if (request == null) {
                return false;
            }
            AbstractResponse response = new CommonClient().execute(request);
            if (response == null) {
                return false;
            }
            return response.getData().getSuccess();
        } catch (Exception e) {
            log.error("检查cookie是否有效出现异常 e:{}", e.getMessage());
            return true;
        }
    }

    private String getCacheKey(String configKey) {
        return Constants.SYS_CONFIG_KEY + configKey;
    }

}
